/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 adv_actor_model_definition.cpp

	$Header: /heroes4/adv_actor_model_definition.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "adv_actor_model_definition.h"

#include "enum_operations.h"
#include "streambuf_operators.h"

// ------------------------------------------------------------------------------
// Unnamed namespace
// ------------------------------------------------------------------------------

namespace
{
	// ------------------------------------------------------------------------------
	// ------------------------------------------------------------------------------
	int const k_current_format_version = 3;

} // Unnamed namespace

// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
bool read( std::streambuf & stream, t_adv_actor_model_definition & definition )
{
	try
	{
		int version = get< t_uint16 >( stream );
		if ( version < 0 || version > k_current_format_version )
			return false;

		definition.set_footprint_size( get< t_uint8 >( stream ) );
		if (version < 2)
		{
			definition.set_prewalk_length( 16 );
			definition.set_walk_length( 32 );
			definition.set_postwalk_length( 16 );
		}
		else
		{
			definition.set_prewalk_length( get<t_uint16>( stream ));
			definition.set_walk_length( get<t_uint16>( stream ));
			definition.set_postwalk_length( get<t_uint16>( stream ));
		}
		std::string action_name;
		int num_actions = get< t_uint16 >( stream );
		while ( num_actions > 0 )
		{
			--num_actions;

			// Read the action name
			stream >> action_name;

			int frames_per_second = get< t_uint8 >( stream );

			std::string sequence_name_array[ k_direction_count ];
			t_direction direction;
			for ( direction = t_direction( 0 ); direction < k_direction_count; enum_incr( direction ) )
				stream >> sequence_name_array[ direction ];

			// Map the action name to an action id
			t_adv_actor_action_id action_id;

			action_id = get_adv_action( action_name );
			if ( action_id >= k_adv_actor_action_count )
				continue;

			definition.set_frames_per_second( action_id, frames_per_second );
			for ( direction = t_direction( 0 ); direction < k_direction_count; enum_incr( direction ) )
				definition.set_sequence_name( action_id, direction, sequence_name_array[ direction ] );
		}

		t_screen_point offset( 0, 0 );
		if ( version >= 1 )
			stream >> offset;
		definition.set_offset( offset );

		t_screen_point flag_offset( 0, 0 );
		if ( version >= 3 )
			stream >> flag_offset;
		definition.set_flag_offset( flag_offset );
	}
	catch ( t_streambuf_read_failure const & )
	{
		return false;
	}
	return true;
}

// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
bool write( std::streambuf & stream, t_adv_actor_model_definition const & definition )
{
	try
	{
		put< t_uint16 >( stream, k_current_format_version );

		put< t_uint8 >( stream, definition.get_footprint_size() );
		put< t_uint16 >(stream, definition.get_prewalk_length() );
		put< t_uint16 >(stream, definition.get_walk_length() );
		put< t_uint16 >(stream, definition.get_postwalk_length() );

		// Write the number of actions
		put< t_uint16 >( stream, k_adv_actor_action_count );
		t_adv_actor_action_id action_id;
		for ( action_id = t_adv_actor_action_id( 0 ); action_id < k_adv_actor_action_count; enum_incr( action_id ) )
		{
			stream << get_adv_action_name( action_id );

			put< t_uint8 >( stream, definition.get_frames_per_second( action_id ) );

			t_direction direction;
			for ( direction = t_direction( 0 ); direction < k_direction_count; enum_incr( direction ) )
				stream << definition.get_sequence_name( action_id, direction );
		}

		stream << definition.get_offset() << definition.get_flag_offset();
	}
	catch ( t_streambuf_write_failure const & )
	{
		return false;
	}
	return true;
}

// ------------------------------------------------------------------------------
// t_resource_traits< t_adv_actor_model_definition > members
// ------------------------------------------------------------------------------

char const t_resource_traits< t_adv_actor_model_definition >::prefix[] = "adv_actor";

char const t_resource_traits< t_adv_actor_model_definition >::extension[] = "aac";
